package cn1shared.ui;

import com.codename1.ui.Button;
import com.codename1.ui.ComboBox;
import com.codename1.ui.Command;
import com.codename1.ui.Component;
import com.codename1.ui.Container;
import com.codename1.ui.Dialog;
import com.codename1.ui.Display;
import com.codename1.ui.Font;
import com.codename1.ui.Graphics;
import com.codename1.ui.Image;
import com.codename1.ui.Label;
import com.codename1.ui.Painter;
import com.codename1.ui.RadioButton;
import com.codename1.ui.TextArea;
import com.codename1.ui.TextField;
import com.codename1.ui.geom.Rectangle;
import com.codename1.ui.layouts.BorderLayout;
import com.codename1.ui.layouts.BoxLayout;
import com.codename1.ui.layouts.FlowLayout;
import com.codename1.ui.layouts.GridLayout;
import com.codename1.ui.layouts.Layout;
import com.codename1.ui.plaf.Border;
import com.codename1.ui.plaf.Style;
import com.codename1.ui.table.TableLayout;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class FormUtils {

	private FormUtils() {} // never

	private static Map<String, Font> fonts;
	private static void initFonts() {
		if (fonts == null) {
			fonts = new HashMap<String, Font>();
			fonts.put("small", Font.createSystemFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL));
			fonts.put("small-bold", Font.createSystemFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_SMALL));
			fonts.put("medium", Font.createSystemFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_MEDIUM));
			fonts.put("medium-bold", Font.createSystemFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_MEDIUM));
			fonts.put("large", Font.createSystemFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_LARGE));
			fonts.put("large-bold", Font.createSystemFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_LARGE));
		}
	}

	public static Font getFont(String type) {
		initFonts();
		return fonts.get(type);
	}

	public static class EasyLabel extends Label {

		public EasyLabel() {
			getStyle().setBgTransparency(0x00);
			font("large");
		}

		public EasyLabel font(String type) {
			getStyle().setFont(getFont(type));
			return this;
		}

		public EasyLabel topSpacing() {
			getStyle().setMargin(Component.TOP, 15);
			return this;
		}

		public EasyLabel noSpacingH() {
			Style style = getStyle();
			style.setMargin(Component.LEFT, 0);
			style.setPadding(Component.LEFT, 0);
			style.setMargin(Component.RIGHT, 0);
			style.setPadding(Component.RIGHT, 0);
			return this;
		}

		public EasyLabel noSpacingV() {
			Style style = getStyle();
			style.setMargin(Component.TOP, 0);
			style.setPadding(Component.TOP, 0);
			style.setMargin(Component.BOTTOM, 0);
			style.setPadding(Component.BOTTOM, 0);
			return this;
		}

		public EasyLabel noSpacing() {
			noSpacingH();
			noSpacingV();
			return this;
		}

		public EasyLabel alignRight() {
			getStyle().setAlignment(Component.RIGHT);
			return this;
		}

		public EasyLabel alignCenter() {
			getStyle().setAlignment(Component.CENTER);
			return this;
		}

		public EasyLabel color(int color) {
			getStyle().setFgColor(color);
			return this;
		}

		public EasyLabel height(float proportion) {
			FormUtils.setHeight(this, proportion);
			return this;
		}

		public EasyLabel background(int color) {
			getStyle().setBgColor(color);
			getStyle().setBgTransparency(0xFF);
			return this;
		}

		public EasyLabel noDots() {
			this.setEndsWith3Points(false);
			return this;
		}

		public EasyLabel asErrorField() {
			return color(0x990000).font("medium");
		}
	}

	public static EasyLabel newLabel() {
		return new EasyLabel();
	}

	public static EasyLabel newLabel(String text) {
		EasyLabel l = newLabel();
		l.setText(text);
		return l;
	}

	public static EasyLabel newLabel(Image img) {
		EasyLabel l = newLabel();
		l.setIcon(img);
		return l;
	}

	public static class EasyTextLabel extends TextArea {
		public EasyTextLabel() {
			setEditable(false);
			setFocusable(false);
			Style style = getStyle();
			style.setBgTransparency(0x00);
			style.setBorder(Border.createEmpty());
		}

		public EasyTextLabel noSpacingV() {
			Style style = getStyle();
			style.setMargin(Component.TOP, 0);
			style.setPadding(Component.TOP, 0);
			style.setMargin(Component.BOTTOM, 0);
			style.setPadding(Component.BOTTOM, 0);
			return this;
		}

		public EasyTextLabel noSpacingH() {
			Style style = getStyle();
			style.setMargin(Component.LEFT, 0);
			style.setPadding(Component.LEFT, 0);
			style.setMargin(Component.RIGHT, 0);
			style.setPadding(Component.RIGHT, 0);
			return this;
		}

		public EasyTextLabel noSpacing() {
			noSpacingV();
			noSpacingH();
			return this;
		}

		public EasyTextLabel topSpacing() {
			Style style = getStyle();
			style.setMargin(Component.TOP, 5);
			style.setPadding(Component.TOP, 0);
			style.setPadding(Component.BOTTOM, 0);
			return this;
		}

		public EasyTextLabel font(String type) {
			getStyle().setFont(getFont(type));
			return this;
		}

		public EasyTextLabel color(int color) {
			getStyle().setFgColor(color);
			return this;
		}

		public EasyTextLabel background(int color) {
			getStyle().setBgColor(color);
			getStyle().setBgTransparency(0xFF);
			return this;
		}

		public EasyTextLabel alignCenter() {
			getStyle().setAlignment(Component.CENTER);
			return this;
		}
	}

	public static EasyTextLabel newTextLabel(String text) {
		EasyTextLabel textArea = newTextLabel();
		textArea.setText(text);
		return textArea;
	}

	public static EasyTextLabel newTextLabel() {
		return new EasyTextLabel();
	}

	public static TextField newTextField() {
		TextField f = new TextField();
		f.getStyle().setFont(getFont("large"));
		f.getSelectedStyle().setFont(getFont("large"));
		return f;
	}

	public static TextField newTextField(String text) {
		TextField f = newTextField();
		f.setText(text);
		return f;
	}

	public static TextField newPasswordField() {
		TextField f = newTextField();
		f.setConstraint(TextField.PASSWORD);
		return f;
	}

	public static TextField newEmailField() {
		TextField f = newTextField();
		f.setConstraint(TextField.EMAILADDR);
		return f;
	}

	public static TextArea newTextArea() {
		TextArea f = new TextArea();
		return f;
	}

	public static Container newContainer() {
		Container c = new Container();
		c.setUIID("_DefaultBg");
		return c;
	}

	public static Container newContainer(Layout layout) {
		Container c = newContainer();
		c.setLayout(layout);
		return c;
	}

	public static class EasyButton extends Button {

		public EasyButton() {}

		public EasyButton font(String type) {
			Font f = getFont(type);
			getStyle().setFont(f);
			getPressedStyle().setFont(f);
			return this;
		}

		public EasyButton transparent() {
			getStyle().setBgTransparency(0x00);
			return this;
		}

		public EasyButton noDots() {
			setEndsWith3Points(false);
			return this;
		}

		public EasyButton background(int color) {
			getStyle().setBgColor(color);
			getStyle().setBgTransparency(0xFF);
			return this;
		}
	}

	public static EasyButton newButton() {
		EasyButton btn = new EasyButton();
		return btn;
	}

	public static EasyButton newButton(String text) {
		EasyButton btn = newButton();
		btn.setText(text);
		return btn;
	}

	public static EasyButton newButton(Image img) {
		EasyButton btn = newButton();
		btn.setIcon(img);
		return btn;
	}

	public static EasyButton newButton(Command cmd) {
		EasyButton btn = newButton();
		btn.setCommand(cmd);
		return btn;
	}

	public static EasyLabel newSeparatorLabel(String title) {
		EasyLabel lbl = new EasyLabel() {
			public void paint(Graphics g) {
				super.paint(g);
				g.drawLine(getX(), getY() + getHeight() - 1, getX() + getWidth(), getY() + getHeight() - 1);
			}
		};
		lbl.setText(title);
		return lbl.font("small");
	}

	public static ComboBox newComboBox(Object[] arr) {
		ComboBox cmb = new ComboBox(arr);
		cmb.getStyle().setBgTransparency(0x00);
		return cmb;
	}

	public static void setBgColor(Component c, int color) {
		c.getStyle().setBgColor(color);
		c.getStyle().setBgTransparency(0xFF);
	}

	public static Container tableY(Component ... components) {
		TableLayout layout = new TableLayout(components.length, 1);
		Container panel = new Container(layout);
		for (Component c : components) {
			panel.addComponent(c);
		}
		return panel;
	}

	public static Container boxY(Component ... components) {
		return box(BoxLayout.Y_AXIS, components);
	}

	public static Container boxX(Component ... components) {
		return box(BoxLayout.X_AXIS, components);
	}

	public static Container boxXNoGrow(Component ... components) {
		return box(BoxLayout.X_AXIS_NO_GROW, components);
	}

	private static Container box(int axis, Component ... components) {
		Layout layout = new BoxLayout(axis);
		Container panel = new Container(layout);
		for (Component c : components) {
			panel.addComponent(c);
		}
		return panel;
	}

	public static Container flow(Component ... components) {
		Layout layout = new FlowLayout();
		Container panel = newContainer(layout);
		for (Component c : components) {
			panel.addComponent(c);
		}
		return panel;
	}

	public static Container gridX(Component ... components) {
		Layout layout = new GridLayout(1, components.length);
		Container panel = newContainer(layout);
		for (Component c : components) {
			panel.addComponent(c);
		}
		return panel;
	}

	public static RadioButton newRadioButton(String text, String group) {
		RadioButton radio = new RadioButton(text);
		radio.setGroup(group);
		setFont(radio, "large");
		radio.getStyle().setBgTransparency(0x00);
		setPadding(radio, 2, 2, 2, 2);
		return radio;
	}

	public static Dialog newEditDialog(String title, Component body) {
		Dialog dialog = new Dialog(title);
		dialog.setLayout(new BorderLayout());
		dialog.addComponent(BorderLayout.CENTER, body);
		dialog.setAutoDispose(false);
		return dialog;
	}

	public static boolean validadeNotEmpty(TextField field) {
		if (field.getText().trim().length() == 0) {
			field.getStyle().setBgColor(0xFFCCCC);
			field.requestFocus();
			return true;
		} else {
			field.getStyle().setBgColor(0xFFFFFF);
		}
		field.repaint();
		return false;
	}

	public static void noMargin(Component c) {
		c.getStyle().setMargin(0,0,0,0);
		c.getPressedStyle().setMargin(0,0,0,0);
		c.getSelectedStyle().setMargin(0,0,0,0);
	}

	public static void noPadding(Component c) {
		c.getStyle().setPadding(0,0,0,0);
		c.getPressedStyle().setPadding(0, 0, 0, 0);
		c.getSelectedStyle().setPadding(0, 0, 0, 0);
	}

	public static void noBorder(Component c) {
		c.getStyle().setBorder(Border.createEmpty());
		c.getPressedStyle().setBorder(Border.createEmpty());
		c.getSelectedStyle().setBorder(Border.createEmpty());
	}

	public static void noSpacing(Component c) {
		noPadding(c);
		noMargin(c);
		noBorder(c);
	}

	public static void setHeight(Component c, float fontProportion) {
		float height = fontProportion * c.getStyle().getFont().getHeight();
		c.setPreferredH((int) height);
	}

	public static void setPadding(Component c, int dipsTop, int dipsBottom, int dipsLeft, int dipsRight) {
		setPadding(c, Component.TOP, dipsTop);
		setPadding(c, Component.BOTTOM, dipsBottom);
		setPadding(c, Component.LEFT, dipsLeft);
		setPadding(c, Component.RIGHT, dipsRight);
	}

	private static final byte[] units = new byte[] {Style.UNIT_TYPE_DIPS,Style.UNIT_TYPE_DIPS,Style.UNIT_TYPE_DIPS,Style.UNIT_TYPE_DIPS};

	public static void setPadding(Component c, int orientation, int dips) {
		c.getStyle().setPaddingUnit(units);
		c.getStyle().setPadding(orientation, dips);
		c.getSelectedStyle().setPaddingUnit(units);
		c.getSelectedStyle().setPadding(orientation, dips);
		c.getPressedStyle().setPaddingUnit(units);
		c.getPressedStyle().setPadding(orientation, dips);
	}

	public static void setPaddingV(Component c, int dips) {
		setPadding(c, Component.TOP, dips);
		setPadding(c, Component.BOTTOM, dips);
	}

	public static void setPaddingH(Component c, int dips) {
		setPadding(c, Component.LEFT, dips);
		setPadding(c, Component.RIGHT, dips);
	}

	public static void setFont(Component c, String font) {
		Font f = getFont(font);
		c.getStyle().setFont(f);
		c.getSelectedStyle().setFont(f);
		c.getPressedStyle().setFont(f);
	}

	public static void focus(TextArea txt) {
		txt.requestFocus();
		Display.getInstance().editString(txt, txt.getMaxSize(), txt.getConstraint(), txt.getText());
	}

	public static Component separator(float fontProportion) {
		Component c = new Container();
		setHeight(c, fontProportion);
		return c;
	}


	private static final Painter LINE_PAINTER = new Painter() {
		@Override
		public void paint(Graphics g, Rectangle rect) {
			g.setColor(0xCCCCCC);
			int mh = (int) (rect.getY() + 0.75 * rect.getHeight());
			g.drawLine(rect.getX(), mh, rect.getX() + rect.getWidth(), mh);
		}
	};

	public static Component separatorLine() {
		Component c = new Container();
		setHeight(c, .25f);
		c.getStyle().setBgPainter(LINE_PAINTER);
		return c;
	}

	public static TableLayout.Constraint c(String spec) {
		List<String> parts = new ArrayList<String>();
		StringBuilder p = new StringBuilder();
		for (int i = 0; i < spec.length(); i++) {
			char c = spec.charAt(i);
			if (c == '|') {
				parts.add(p.toString());
				p = new StringBuilder();
			} else
				p.append(c);
		}
		parts.add(p.toString());
		TableLayout.Constraint c = new TableLayout.Constraint();
		for (String part : parts) {
			if (part.startsWith("span"))
				c.setHorizontalSpan(Integer.valueOf(part.substring(4)));
			else if ("center".equals(part))
				c.setHorizontalAlign(Component.CENTER);
			else if ("right".equals(part))
				c.setHorizontalAlign(Component.RIGHT);
			else if ("top".equals(part))
				c.setVerticalAlign(Component.TOP);
			else if ("middle".equals(part))
				c.setVerticalAlign(Component.CENTER);
			else if (part.startsWith("width"))
				c.setWidthPercentage(Integer.valueOf(part.substring(5)));
			else if (part.startsWith("height"))
				c.setHeightPercentage(Integer.valueOf(part.substring(6)));
		}
		return c;
	}
}
